#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
#include <pthread.h>
#include <semaphore.h>
#if 0
struct Test
{
    int num;
    int age;
};    
void* callback(void* arg)
{
    for(int i = 0;i < 5;i++)
    {
        printf("子线程:i = %d\n",i);
    }
    printf("子线程: %ld\n",pthread_self());
    struct Test* t = (struct Test*)arg;
    t->num = 100;
    t->age = 6;
    pthread_exit(t);
    return NULL;
}
int main()
{
    struct Test t;
    pthread_t tid;
    pthread_create(&tid,NULL,callback,&t);
    printf("主线程: %ld\n",pthread_self());
    pthread_detach(tid);
    pthread_exit(NULL);
    //void* ptr;
    // pthread_join(tid,&ptr);
    // printf("num = %d,age = %d\n",t.num,t.age);
    return 0;
}
#endif
#if 0
#define MAX 50
// 全局变量
int number;
pthread_mutex_t mutex;
// 线程处理函数
void* funcA_num(void* arg)
{
    for(int i=0; i<MAX; ++i)
    {
        pthread_mutex_lock(&mutex);
        int cur = number;
        cur++;
        usleep(10);
        number = cur;
        printf("Thread A, id = %lu, number = %d\n", pthread_self(), number);
        pthread_mutex_unlock(&mutex);
    }

    return NULL;
}

void* funcB_num(void* arg)
{
    for(int i=0; i<MAX; ++i)
    {
        pthread_mutex_lock(&mutex);
        int cur = number;
        cur++;
        number = cur;
        printf("Thread B, id = %lu, number = %d\n", pthread_self(), number);
        usleep(5);
        pthread_mutex_unlock(&mutex);
    }

    return NULL;
}

int main(int argc, const char* argv[])
{
    pthread_t p1, p2;
    pthread_mutex_init(&mutex,NULL);
    // 创建两个子线程
    pthread_create(&p1, NULL, funcA_num, NULL);
    pthread_create(&p2, NULL, funcB_num, NULL);

    // 阻塞，资源回收
    pthread_join(p1, NULL);
    pthread_join(p2, NULL);
    pthread_mutex_destroy(&mutex);
    return 0;
}
#endif
#if 0
// 全局变量
int number = 0;

// 定义读写锁
pthread_rwlock_t rwlock;

// 写的线程的处理函数
void* writeNum(void* arg)
{
    while(1)
    {
        pthread_rwlock_wrlock(&rwlock);
        int cur = number;
        cur ++;
        number = cur;
        printf("++写操作完毕, number : %d, tid = %ld\n", number, pthread_self());
        pthread_rwlock_unlock(&rwlock);
        // 添加sleep目的是要看到多个线程交替工作
        usleep(rand() % 100);
    }

    return NULL;
}

// 读线程的处理函数
// 多个线程可以如果处理动作相同, 可以使用相同的处理函数
// 每个线程中的栈资源是独享
void* readNum(void* arg)
{
    while(1)
    {
        pthread_rwlock_rdlock(&rwlock);
        printf("--全局变量number = %d, tid = %ld\n", number, pthread_self());
        pthread_rwlock_unlock(&rwlock);
        usleep(rand() % 100);
    }
    return NULL;
}

int main()
{
    // 初始化读写锁
    pthread_rwlock_init(&rwlock, NULL);

    // 3个写线程, 5个读的线程
    pthread_t wtid[3];
    pthread_t rtid[5];
    for(int i=0; i<3; ++i)
    {
        pthread_create(&wtid[i], NULL, writeNum, NULL);
    }

    for(int i=0; i<5; ++i)
    {
        pthread_create(&rtid[i], NULL, readNum, NULL);
    }

    // 释放资源
    for(int i=0; i<3; ++i)
    {
        pthread_join(wtid[i], NULL);
    }

    for(int i=0; i<5; ++i)
    {
        pthread_join(rtid[i], NULL);
    }

    // 销毁读写锁
    pthread_rwlock_destroy(&rwlock);

    return 0;
}
#endif
#if 0
//链表实现一个任务队列，生产者消费者模型
struct Node//链表节点
{
    int number;
    struct Node* next;
};
//链表的头节点
struct Node* head = NULL; 
pthread_mutex_t mutex;
pthread_cond_t cond;
//生产者
void* producer(void* arg)
{
    while(1)
    {
        pthread_mutex_lock(&mutex);
        struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
        newNode->number = rand() % 1000;
        newNode->next = head;
        head = newNode;
        printf("生产者的id是 %ld , number = %d\n",pthread_self(),newNode->number);
        pthread_mutex_unlock(&mutex);
        pthread_cond_broadcast(&cond);//生产完了，唤醒阻塞的消费者函数
        sleep(rand() % 3);
    }
    return NULL;
}
//消费者
void* consumer(void* arg)
{
    while(1)
    {
        pthread_mutex_lock(&mutex);
        while(head == NULL)
        {
            //阻塞消费者线程
            pthread_cond_wait(&cond,&mutex);
        }
        struct Node* node = head;
        printf("消费者的id是 %ld , number = %d\n",pthread_self(),node->number);
        head = head->next;
        free(node); 
        pthread_mutex_unlock(&mutex);
        sleep(rand() % 3);
    }
    return NULL;
}
//主函数
int main()
{
    //初始化条件变量和锁
    pthread_mutex_init(&mutex,NULL);
    pthread_cond_init(&cond,NULL);
    pthread_t t1[5],t2[5];
    for(int i = 0; i < 5; ++i)
    {
        pthread_create(&t1[i],NULL,producer,NULL);
    }
    for(int i = 0;i < 5; ++i)
    {
        pthread_create(&t2[i],NULL,consumer,NULL);
    }
    for(int i = 0; i < 5; ++i)
    {
        pthread_join(t1[i],NULL);
        pthread_join(t2[i],NULL);
    }
    pthread_mutex_destroy(&mutex);
    pthread_cond_destroy(&cond);
}
#endif
#if 0
//信号量实现生产者消费者模型(资源总数为1)
//生产者的信号量
sem_t semp;
//消费者的信号量
sem_t semc;
struct Node//链表节点
{
    int number;
    struct Node* next;
};
//链表的头节点
struct Node* head = NULL; 
//生产者
void* producer(void* arg)
{
    while(1)
    {
        sem_wait(&semp);
        struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
        newNode->number = rand() % 1000;
        newNode->next = head;
        head = newNode;
        printf("生产者的id是 %ld , number = %d\n",pthread_self(),newNode->number);
        sem_post(&semc);
        sleep(rand() % 3);
    }
    return NULL;
}
//消费者
void* consumer(void* arg)
{
    while(1)
    {
        sem_wait(&semc);    
        struct Node* node = head;
        printf("消费者的id是 %ld , number = %d\n",pthread_self(),node->number);
        head = head->next;
        free(node); 
        sem_post(&semp);
        sleep(rand() % 3);
    }
    return NULL;
}
//主函数
int main()
{
    //生产者
    sem_init(&semp,0,1);
    //消费者 -> 资源数量初始化为0，消费者线程刚启动就阻塞了
    sem_init(&semc,0,0);
    pthread_t t1[5],t2[5];
    for(int i = 0; i < 5; ++i)
    {
        pthread_create(&t1[i],NULL,producer,NULL);
    }
    for(int i = 0;i < 5; ++i)
    {
        pthread_create(&t2[i],NULL,consumer,NULL);
    }
    for(int i = 0; i < 5; ++i)
    {
        pthread_join(t1[i],NULL);
        pthread_join(t2[i],NULL);
    }
    sem_destroy(&semp);
    sem_destroy(&semc);
    return 0;
}
#endif

//信号量实现生产者消费者模型(资源总数为1)
//生产者的信号量
sem_t semp;
//消费者的信号量
sem_t semc;
//锁
pthread_mutex_t mutex;
struct Node//链表节点
{
    int number;
    struct Node* next;
};
//链表的头节点
struct Node* head = NULL; 
//生产者
void* producer(void* arg)
{
    while(1)
    {
        sem_wait(&semp);
        pthread_mutex_lock(&mutex);
        struct Node* newNode = (struct Node*)malloc(sizeof(struct Node));
        newNode->number = rand() % 1000;
        newNode->next = head;
        head = newNode;
        printf("生产者的id是 %ld , number = %d\n",pthread_self(),newNode->number);
        pthread_mutex_unlock(&mutex);
        sem_post(&semc);
        sleep(rand() % 3);
    }
    return NULL;
}
//消费者
void* consumer(void* arg)
{
    while(1)
    {
        sem_wait(&semc);
        pthread_mutex_lock(&mutex);    
        struct Node* node = head;
        printf("消费者的id是 %ld , number = %d\n",pthread_self(),node->number);
        head = head->next;
        free(node); 
        pthread_mutex_unlock(&mutex);
        sem_post(&semp);
        sleep(rand() % 3);
    }
    return NULL;
}
//主函数
int main()
{
    //生产者
    sem_init(&semp,0,5);
    //消费者 -> 资源数量初始化为0，消费者线程刚启动就阻塞了
    sem_init(&semc,0,0);
    pthread_mutex_init(&mutex,NULL);
    pthread_t t1[5],t2[5];
    for(int i = 0; i < 5; ++i)
    {
        pthread_create(&t1[i],NULL,producer,NULL);
    }
    for(int i = 0;i < 5; ++i)
    {
        pthread_create(&t2[i],NULL,consumer,NULL);
    }
    for(int i = 0; i < 5; ++i)
    {
        pthread_join(t1[i],NULL);
        pthread_join(t2[i],NULL);
    }
    pthread_mutex_destroy(&mutex);
    sem_destroy(&semp);
    sem_destroy(&semc);
    return 0;
}